#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
The typedef mechanism allows the creation of aliases for other types. It does not create new types. 

C 语言提供了 typedef 关键字，您可以使用它来为类型取一个新的名字
    typedef unsigned char BYTE;
    在这个类型定义之后，标识符 BYTE 可作为类型 unsigned char 的缩写
    BYTE  b1, b2;
按照惯例，定义时会大写字母，以便提醒用户类型名称是一个象征性的缩写，但您也可以使用小写字母


typedef vs #define
    #define 是 C 指令，用于为各种数据类型定义别名，
    与 typedef 类似，但是它们有以下几点不同：
        typedef 仅限于为类型定义符号名称，
        #define 不仅可以为类型定义别名，也能为数值定义别名，比如您可以定义 1 为 ONE。
        typedef 是由编译器执行解释的，#define 语句是由预编译器进行处理的。
*/

/* 一、      Typedef for Structures and Unions           */

// alias "struct Books" as Book
typedef struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} Book;

// alias TRUE AS 1
#define TRUE  1
#define FALSE 0

/*
Note that the name Person (as opposed to struct Person) is not defined until the final semicolon. Thus for linked
lists and tree structures which need to contain a pointer to the same structure type, you must use either:

*/
typedef struct Person {
    char name[32];
    int age;
    struct Person *next;
} Person;

//or:

typedef struct Person Person;
struct Person {
    char name[32];
    int age;
    Person *next;
};


// The use of a typedef for a union type is very similar.
typedef union Float Float;
union Float
{
    float f;
    char b[sizeof(float)];
};


/* 二、      Typedef for Function Pointers          */

/*
We can use typedef to simplify the usage of function pointers. 
Imagine we have some functions, all having thesame signature, 
that use their argument to print out something in different ways:

*/
void print_to_n(int n)
{
    for (int i = 1; i <= n; ++i)
        printf("%d\n", i);
}

void print_n(int n)
{
    printf("%d\n", n);
}

// Now we can use a typedef to create a named function pointer type called printer:
typedef void (*printer_t)(int);

/*
This creates a type, named printer_t for a pointer to a function that takes a single int argument and returns
nothing, which matches the signature of the functions we have above. To use it we create a variable of the created
type and assign it a pointer to one of the functions in question:

*/
printer_t p = &print_to_n;
void (*p)(int) = &print_to_n; // This would be required without the type
// Then to call the function pointed to by the function pointer variable:

/*
Thus the typedef allows a simpler syntax when dealing with function pointers. This becomes more apparent when
function pointers are used in more complex situations, such as arguments to functions.
If you are using a function that takes a function pointer as a parameter without a function pointer type defined the
function definition would be,
*/
void foo (void (*printer)(int), int y){
    //code
    printer(y);
    //code
}

// However, with the typedef it is:
void foo (printer_t printer, int y){
    //code
    printer(y);
    //code
}

/*
Likewise functions can return function pointers and again, the use of a typedef can make the syntax simpler when
doing so.

A classic example is the signal function from <signal.h>. The declaration for it (from the C standard) is:
*/
void (*signal(int sig, void (*func)(int)))(int);

/*
That's a function that takes two arguments — an int and a pointer to a function which takes an int as an argument
and returns nothing — and which returns a pointer to function like its second argument.
If we defined a type SigCatcher as an alias for the pointer to function type:

*/
typedef void (*SigCatcher)(int);
// then we could declare signal() using:
SigCatcher signal(int sig, SigCatcher func);

/*
On the whole, this is easier to understand (even though the C standard did not elect to define a type to do the job).
The signal function takes two arguments, an int and a SigCatcher, and it returns a SigCatcher — where a
SigCatcher is a pointer to a function that takes an int argument and returns nothing.
Although using typedef names for pointer to function types makes life easier, it can also lead to confusion for
others who will maintain your code later on, so use with caution and proper documentation. See also Function
Pointers.
*/


/* 三、           Simple Uses of Typedef          */
// For giving short names to a data type

// Instead of:
long long int fo;
struct mystructure object;

// one can use
/* write once */
typedef long long ll;
typedef struct mystructure mystruct;
/* use whenever needed */
ll fo;
mystruct object;

int main( )
{
   Book book;
 
   strcpy( book.title, "C tutorial");
   strcpy( book.author, "Runoob");
   strcpy( book.subject, "paogramming language");
   book.book_id = 12345;
 
   printf( "title : %s\n", book.title);
   printf( "author : %s\n", book.author);
   printf( "category : %s\n", book.subject);
   printf( "book ID : %d\n", book.book_id);


    printf( "TRUE value: %d\n", TRUE);
    printf( "FALSE value: %d\n", FALSE);

    p(5); // Prints 1 2 3 4 5 on separate lines
    (*p)(5); // So does this
    system("pause");
   return 0;
}





